import { MindGraph } from "./MindGraph";

import { ViewOptions, Size } from './models'
import { LayoutProvider } from './LayoutProvider';
import { Node } from './Node'
import * as MGUtils from './utils'

export class ViewProvider {
    mindGraph: MindGraph = null
    opts: ViewOptions = null
    layout: LayoutProvider = null

    // 用户提供id的 DOM 对象
    container: HTMLElement = null
    // 第一层 div 元素，DOM对象，其 class 有 jsmind-inner
    ePanel: HTMLElement = null
    // canvas 对象
    eCanvas: HTMLCanvasElement = null
    // 标签为 jmnodes 的 DOM 对象
    eNodes: HTMLElement = null
    // 输入框
    eEditor: HTMLInputElement = null

    // Canvas 的上下文环境
    canvasCtx: CanvasRenderingContext2D = null
    // 大小
    size: Size = { w: 0, h: 0}

    // 选中的节点
    selectedNode: Node = null

    // 正在编辑的节点
    editingNode: Node = null

    // 缩放相关
    actualZoom: number = 1
    zoomStep = 0.1
    minZoom = 0.5
    maxZoom = 2

    constructor(mindGraph: MindGraph, options: ViewOptions) {
        this.mindGraph = mindGraph
        this.opts = options
        this.layout = mindGraph.layout
        this.container =  null
        this.ePanel = null
        this.eNodes = null
        this.eCanvas = null
        this.canvasCtx = null
        this.size = { w: 0, h: 0}
        this.selectedNode = null
        this.editingNode = null
    }

    /**
     * 视图初始化
     */
    init() {
        console.debug('view.init');

        this.container = MGUtils.DomUtils.$i(this.opts.container) ? (this.opts.container) as HTMLElement : MGUtils.DomUtils.$g((this.opts.container) as string);
        if(!this.container){
            console.error('the options.view.container was not be found in dom');
            return;
        }
        this.ePanel = MGUtils.DomUtils.$c('div');
        this.eCanvas = MGUtils.DomUtils.$c('canvas') as HTMLCanvasElement;
        this.eNodes = MGUtils.DomUtils.$c('jmnodes');
        this.eEditor = MGUtils.DomUtils.$c('input') as HTMLInputElement;

        this.ePanel.className = 'jsmind-inner';
        this.ePanel.appendChild(this.eCanvas);
        this.ePanel.appendChild(this.eNodes);

        this.eEditor.className = 'jsmind-editor';
        this.eEditor.type = 'text';

        this.actualZoom = 1;
        this.zoomStep = 0.1;
        this.minZoom = 0.5;
        this.maxZoom = 2;

        var v = this;
        MGUtils.DomUtils.addEvent(this.eEditor, 'keydown', function(e){
            var evt = e || event;
            if(evt.keyCode == 13){v.editNodeEnd();evt.stopPropagation();}
        });
        MGUtils.DomUtils.addEvent(this.eEditor,'blur',function(e){
            v.editNodeEnd();
        });

        this.container.appendChild(this.ePanel);

        this.initCanvas();
    }

    /**
     * canvas 初始化
     */
    initCanvas() {
        var ctx = this.eCanvas.getContext('2d');
        this.canvasCtx = ctx;
    }

    /**
     * 编辑结束
     */
    editNodeEnd() {
        if(this.editingNode != null){
            var node = this.editingNode;
            this.editingNode = null;
            var view_data = node._data.view;
            var element = view_data.element;
            var topic = this.eEditor.value;
            element.style.zIndex = 'auto';
            element.removeChild(this.eEditor);
            if(MGUtils.CommonUtils.isEmpty(topic) || node.topic === topic){
                if(this.opts.support_html){
                    MGUtils.DomUtils.$h(element,node.topic);
                }else{
                    MGUtils.DomUtils.$t(element,node.topic);
                }
            }else{
                this.mindGraph.updateNode(node.id,topic);
            }
        } 
    }


    /**
     * 是否正在编辑
     */
    isEditing(): boolean {
        return !!this.editingNode
    }

    /**
     * 元素是否是扩展器
     * @param element 
     */
    isExpander (element: HTMLElement) {
        return (element.tagName.toLowerCase() == 'jmexpander');
    }

    /**
     * 保存节点的位置
     * @param node 
     */
    saveLocation (node: Node) {
        var vd = node._data.view;
        vd._saved_location={
            x:parseInt(vd.element.style.left)-this.ePanel.scrollLeft,
            y:parseInt(vd.element.style.top)-this.ePanel.scrollTop,
        };
    }

    reset() {
        console.debug('view.reset')
        this.selectedNode = null
        this.clearLines()
        this.clearNodes()
        this.resetTheme()
    }


    /**
     * 重新布局 
     * TODO:
     */
    relayout () {
        this.expandSize();
        this._show();
    }

    /**
     * TODO:
     * @param node 
     */
    restoreLocation (node: Node) {

    }

    /**
     * TODO:
     */
    expandSize() {

    }

    /**
     * TODO:
     */
    private _show() {

    }

    /**
     * 为 <jsnodes> 标签元素添加事件，事件处理函数在 MindGraph 中
     * @param obj 
     * @param eventName 
     * @param eventHandle 
     */
    addEvent(obj: MindGraph, eventName: string, eventHandle: any) {
        MGUtils.DomUtils.addEvent(this.eNodes, eventName, function (e) {
            let evt = e || event
            eventHandle.call(obj, evt)
        })
    }

    /**
     * 根据 DOM 节点中的 nodeid 属性，获取 id
     * @param element 
     */
    getBindedNodeId (element: HTMLElement) {
        if(element == null){
            return null;
        }
        var tagName = element.tagName.toLowerCase();
        if(tagName == 'jmnodes' || tagName == 'body' || tagName == 'html'){
            return null;
        }
        if(tagName == 'jmnode' || tagName == 'jmexpander'){
            return element.getAttribute('nodeid');
        }else{
            return this.getBindedNodeId(element.parentElement);
        }
    }

    /**
     * 设置选中，修改样式
     * @param node 
     */
    selectNode (node: Node) {
        // 去掉 旧选中 节点的 selected 类
        if(!!this.selectedNode){
            this.selectedNode._data.view.element.className =
            this.selectedNode._data.view.element.className.replace(/\s*selected\b/i,'');
            this.resetNodeCustomStyle(this.selectedNode);
        }
        // 设置新选中节点
        if(!!node){
            this.selectedNode = node;
            node._data.view.element.className += ' selected';
            // 清除背影和 color? 为什么？ TODO
            this.clearNodeCustomStyle(node);
        }
    }

    /**
     * 清除所有选中的样式
     */
    selectClear () {
        this.selectNode(null);
    }
    /**
     * 设置 node 为普通样式
     * @param node 
     */
    resetNodeCustomStyle(node: Node) {
        this._reset_node_custom_style(node._data.view.element, node.data);
    }

    clearNodeCustomStyle(node: Node) {
        var node_element = node._data.view.element;
        node_element.style.backgroundColor = "";
        node_element.style.color = "";
    }

    private _reset_node_custom_style(node_element: HTMLElement, node_data) {
        if('background-color' in node_data){
            node_element.style.backgroundColor = node_data['background-color'];
        }
        if('foreground-color' in node_data){
            node_element.style.color = node_data['foreground-color'];
        }
        if('width' in node_data){
            node_element.style.width = node_data['width']+'px';
        }
        if('height' in node_data){
            node_element.style.height = node_data['height']+'px';
        }
        if('font-size' in node_data){
            node_element.style.fontSize = node_data['font-size']+'px';
        }
        if('font-weight' in node_data){
            node_element.style.fontWeight = node_data['font-weight'];
        }
        if('font-style' in node_data){
            node_element.style.fontStyle = node_data['font-style'];
        }
        if('background-image' in node_data) {
            var backgroundImage = node_data['background-image'];
            if (backgroundImage.startsWith('data') && node_data['width'] && node_data['height']) {
                var img = new Image();

                img.onload = function() {
                    // var c = MGUtils.DomUtils.$c('canvas') as HTMLCanvasElement;
                    // c.width = node_element.clientWidth;
                    // c.height = node_element.clientHeight;
                    // var img = this;
                    // if(c.getContext) {
                    //     var ctx = c.getContext('2d');
                    //     ctx.drawImage(img, 2, 2, node_element.clientWidth, node_element.clientHeight);
                    //     var scaledImageData = c.toDataURL();
                    //     node_element.style.backgroundImage='url('+scaledImageData+')';
                    // }
                };
                img.src = backgroundImage;

            } else {
                node_element.style.backgroundImage='url('+backgroundImage+')';
            }
            node_element.style.backgroundSize='99%';

            if('background-rotation' in node_data){
                node_element.style.transform = 'rotate(' + node_data['background-rotation'] + 'deg)';
            }

        }
    }

    /**
     * 清除 canvas
     */
    clearLines() {
        MGUtils.CanvasUtils.clear(this.canvasCtx, 0, 0, this.size.w, this.size.h);
    }

    /**
     * 清除 nodes
     */
    clearNodes () {
        var mind = this.mindGraph.mind;
        if(mind == null){
            return;
        }
        var nodes = mind.nodes;
        var node = null;
        for(var nodeid in nodes){
            node = nodes[nodeid];
            node._data.view.element = null;
            node._data.view.expander = null;
        }
        this.eNodes.innerHTML = '';
    }

    /**
     * 重置主题
     */
    resetTheme () {
        var theme_name = this.mindGraph.options.theme;
        if(!!theme_name){
            this.eNodes.className = 'theme-' + theme_name;
        }else{
            this.eNodes.className = '';
        }
    }

}